package com.fadadianqi.logistics.search;

import com.fadadianqi.logistics.customer.model.Customer;
import com.fadadianqi.logistics.customer.model.Town;
import com.fadadianqi.logistics.customer.model.Village;
import com.fadadianqi.logistics.customer.service.CustomerService;
import com.fadadianqi.goods.model.Brand;
import com.fadadianqi.goods.model.Category;
import com.fadadianqi.goods.model.Goods;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.search.AbstractIndexService;
import com.fadadianqi.search.IndexPathHelper;
import com.fadadianqi.search.IndexPathHelper.IndexEnum;
import com.fadadianqi.logistics.sell.model.Bill;
import com.fadadianqi.logistics.sell.model.Item;
import com.fadadianqi.logistics.sell.service.BillService;
import com.yeqiangwei.commons.util.Pagination;
import com.yeqiangwei.commons.util.Pagination.Order;
import com.yeqiangwei.commons.util.ValidatorHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("sellIndexService")
public class SellIndexService extends AbstractIndexService {

    private static final Log log = LogFactory.getLog(SellIndexService.class);

    private IndexPathHelper indexPathHelper = new IndexPathHelper(IndexEnum.SELL);

    private String newPath;

    public SellIndexService() {

    }

    @Override
    protected String getCurrentIndexPath() {
        return indexPathHelper.getIndexPath();
    }

    @Override
    protected String getNewIndexPath() {
        newPath = indexPathHelper.createNewPath();
        return newPath;
    }

    @Override
    protected void changeIndexPath() {
        indexPathHelper.savePath(newPath);
    }

    protected void build(IndexWriter writer, boolean rebuild) throws Exception {
        synchronized (writer) {
            int limit = 1000;
            int total = billService.countAll();
            int pages = total / limit;
            if (total % limit != 0) {
                pages++;
            }
            for (int page = 1; page <= pages; page++) {
                Pagination pagination = new Pagination(page, limit);
                pagination.setOrderList(new Order[]{Pagination.getNewOrder("add_time", Order.ASCENDING)});
                List<Bill> list = billService.findAll(pagination);
                if (ValidatorHelper.isEmpty(list)) {
                    continue;
                }
                for (Bill item : list) {
                    try {
                        writer.addDocument(documentBuilder(item));
                    } catch (Exception e) {
                        log.error(e);
                    }
                }
            }
            writer.optimize();
            writer.close(true);
        }
    }

    public static final String FIELD_CUSTOMER_NAME = "customerName";
    public static final String FIELD_TOWN_NAME = "townName";
    public static final String FIELD_VILLAGE_NAME = "villageName";
    public static final String FIELD_ID = "id";
    public static final String FIELD_DETAILS = "details";
    public static final String FIELD_ADD_TIME = "addTime";

    protected Document documentBuilder(Object o) throws Exception {
        Bill bill = (Bill) o;
        Document doc = new Document();
        Town town = null;
        Village village = null;

        Customer customer = customerService.getById(bill.getCustomerId());
        if (customer != null) {
            town = customerService.getTownById(customer.getTownId());
            village = customerService.getVillageById(customer.getVillageId());
        }

        List<Item> items = billService.findItemsByBillId(bill.getId());

        StringBuilder detailsBuf = new StringBuilder();

        if (customer != null) {
            String tmp = customer.getName() + " " + super.toPinyinIndexContent(customer.getName());
            Field customerName = new Field(FIELD_CUSTOMER_NAME, tmp, Store.YES, Index.ANALYZED);
            doc.add(customerName);
        }

        for (Item item : items) {
            Goods goods = goodsService.getGoodsById(item.getGoodsId());
            Brand brand = goodsService.getBrandById(item.getBrandId());
            Category category = goodsService.getCategoryById(item.getCategoryId());
            detailsBuf.append(goods.getName());
            detailsBuf.append(" ");
            detailsBuf.append(goods.getDisplayName());
            detailsBuf.append(" ");
            detailsBuf.append(goods.getPinyin());
            detailsBuf.append(" ");
            detailsBuf.append(brand.getName());
            detailsBuf.append(" ");
            detailsBuf.append(brand.getPinyin());
            detailsBuf.append(" ");
            detailsBuf.append(category.getName());
            detailsBuf.append(" ");
            detailsBuf.append(category.getPinyin());
            detailsBuf.append(" ");
        }
        Field details = new Field(FIELD_DETAILS, detailsBuf.toString(), Store.YES, Index.ANALYZED);
        doc.add(details);

        Field id = new Field(FIELD_ID, bill.getId(), Store.YES, Index.ANALYZED);
        doc.add(id);

        if (town != null) {
            String tmp = town.getName() + " " + super.toPinyinIndexContent(town.getName());
            Field townName = new Field(FIELD_TOWN_NAME, tmp, Store.YES, Index.ANALYZED);
            doc.add(townName);
        }

        if (village != null) {
            String tmp = village.getName() + " " + super.toPinyinIndexContent(village.getName());
            Field villageName = new Field(FIELD_VILLAGE_NAME, tmp, Store.YES, Index.ANALYZED);
            doc.add(villageName);
        }

        long _addTime = bill.getAddTime().getTime();
        NumericField addTime = new NumericField(FIELD_ADD_TIME, Store.YES, Boolean.TRUE);
        addTime.setLongValue(_addTime);
        doc.add(addTime);

        if (log.isDebugEnabled()) {
            log.debug(doc.toString());
        }
        return doc;
    }

    private static Boolean IS_RUNNING = Boolean.FALSE;

    public synchronized boolean isRunning() {
        return IS_RUNNING;
    }

    protected synchronized void lock() {
        IS_RUNNING = true;
    }

    protected synchronized void unlock() {
        IS_RUNNING = false;
    }

    @Autowired
    private BillService billService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private GoodsService goodsService;
}
